<template>
	<view id="event-source" :props="mergeProps" :change:props="eventSource.renderPropsChange" v-show="false">
	</view>
</template>

<script>
	export default {
		props: {
			url: {
				type: String,
				default: "",
			},
			options: {
				type: Object,
				default: () => ({}),
			},
		},
		data() {
			return {
				isSend: false,
				isClose: false
			}
		},
		computed: {
			// 合并传入renderjs的数据
			mergeProps({
				url,
				options,
				isSend,
				isClose
			}) {
				return {
					url,
					options,
					isSend,
					isClose
				};
			},
		},
		methods: {
			// 发送
			send() {
				this.isSend = true;
				this.$nextTick(() => {
					this.isSend = false;
				});
			},
			close() {
				this.isClose = true;
				this.$nextTick(() => {
					this.isClose = false;
				});
			},
			// 处理renderjs发回的数据
			emits(e) {
				this.$emit("callback", {
					...e
				});
			},
		},
	};
</script>

<script module="eventSource" lang="renderjs">
	import { fetchEventSource } from "@microsoft/fetch-event-source";
	import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
	export default {
		data() {
			return {
				abortController: null
			}
		},
		methods: {
			// 传入数据变更
			renderPropsChange(nVal) {
				const { url, isSend, isClose } = nVal || {};
				if (isClose && this.abortController) {
					this.abortController.abort()
				}
				if (!isSend) return;
				if (!url) return this.handleEmitData({
					type: "tip",
					msg: "URL cannot be empty."
				});
				this.$nextTick(() => {
					this.handleSSE(nVal);
				});
			},
			// 发送数据到service层
			handleEmitData(data = {}) {
				this.$ownerInstance.callMethod('emits', data);
			},
			// 处理SSE
			handleSSE(opts = {}) {
				const that = this;
				// 检查浏览器是否支持SSE
				if (!('EventSource' in window)) return this.handleEmitData({
					type: "tip",
					msg: "The current device does not support EventSource."
				});
				const { url, options = {}} = opts || {};
				this.abortController = new AbortController()
				options.signal = this.abortController.signal
				fetchEventSource(url, {
					...options,
					onopen() {
						that.handleEmitData({
							type: "onopen",
							msg: "EventSource onopen."
						});
					},
					onmessage(res) {
						that.handleEmitData({
							type: "onmessage",
							msg: "EventSource onmessage.",
							data: res.data
						});
					},
					onclose() {
						that.handleEmitData({
							type: "onclose",
							msg: "EventSource onclose."
						});
					},
					onerror(error) {
						that.handleEmitData({
							type: "onerror",
							msg: "EventSource onerror.",
							data: JSON.stringify(error)
						});
					}
				});
			}
		}
	}
</script>